package com.ccteam.fluidmusic.ui

import androidx.lifecycle.*
import com.ccteam.fluidmusic.fluidmusic.common.MusicServiceConnectionFlow
import com.ccteam.fluidmusic.utils.Event
import com.ccteam.fluidmusic.utils.OnceLiveData
import com.ccteam.network.ApiError
import com.ccteam.network.ApiResult
import com.ccteam.shared.core.UserCore
import com.ccteam.shared.data.auth.AuthRepository
import com.ccteam.shared.datastore.protobuf.UserInfoProtos
import com.orhanobut.logger.Logger
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * @author Xiaoc
 * @since 2021/3/19
 *
 * 引导页ViewModel，负责管理跳转相关事宜
 * 并检测用户Token是否过期
 */
@HiltViewModel
class SplashViewModel @Inject constructor(
    private val authRepository: AuthRepository,
    private val userCore: UserCore,
    private val musicServiceConnectionFlow: MusicServiceConnectionFlow
) : ViewModel() {

    companion object{
        const val MIN_WAIT_TIME = 600L
        const val MAX_WAIT_TIME = 3000L
    }

    private var stopForwardToNextActivity: Boolean = false

    /**
     * 是否应该跳转至MainActivity
     * 当等待任务结束后，会将其设置为 true
     */
    private val _shouldForwardToNextActivity = MutableLiveData<Boolean>()
    val shouldForwardToNextActivity: LiveData<Boolean> get() = _shouldForwardToNextActivity

    /**
     * 进入Logo页的时间
     */
    private val enterTime = System.currentTimeMillis()

    /**
     * 是否已经处于准备跳转中
     */
    @Volatile var isForwarding: Boolean = false

    private val _userInfo = MutableLiveData<UserInfoProtos.UserInfo>()

    /**
     * 当前登录是否有效
     */
    private val _isLogin = MediatorLiveData<Boolean>()
    val isLogin: LiveData<Boolean> get() = _isLogin

    private val _errorMessage = MutableLiveData<Event<String>>()
    val errorMessage: LiveData<Event<String>> get() = _errorMessage

    private val _isConnected = OnceLiveData<Boolean>()
    val isConnected: LiveData<Boolean> get() = _isConnected

    init {
        _isLogin.addSource(_userInfo){
            checkUserLogin()
        }
        viewModelScope.launch {
            userCore.readLoginState().collectLatest {
                _userInfo.value = it
            }
        }

        viewModelScope.launch {
            musicServiceConnectionFlow.isConnected.collectLatest {
                _isConnected.setValue(it)
            }
        }

        /**
         * 默认设置一个最长等待时长的任务，当达到后强制跳转到下一个界面
         */
        viewModelScope.launch {
            delay(MAX_WAIT_TIME)
            forwardToNextActivity()
        }
    }

    /**
     * 开屏检查用户是否处于登录状态
     * 如果Token已经失效，则提示用户进行登录，并进行DataStore的登出信息修改
     */
    private fun checkUserLogin(){
        _userInfo.value?.let {
            if(it.userToken.isNullOrEmpty()){
                _isLogin.value = false
                return
            }
            Logger.d("检测Token是否失效：${it.userToken}")

            viewModelScope.launch {
                val result = authRepository.checkUserLogin(it.userToken)
                if(result is ApiResult.Success){
                    if(result.data.success){
                        // Token没过期，则登录成功，且不用修改DataStore信息，因为没过期不用关心
                        _isLogin.value = true
                    }
                } else if(result is ApiResult.Failure){
                    Logger.d("Token错误代码：${result.errorCode}")
                    // 如果是服务端返回的错误，则进行错误提醒
                    if(result.errorCode == ApiError.serverErrorCode){
                        _isLogin.value = false
                        // Token失效，进行DataStore中的登出操作
                        userCore.logout()
                        _errorMessage.value = Event(result.errorMsg)
                    }
                }
            }
        }
    }

    /**
     * 设置是否停止跳转到MainActivity
     */
    fun showPermissionFragment(show: Boolean){
        stopForwardToNextActivity = show
    }

    fun forwardToNextActivity(){
        viewModelScope.launch {
            if(!isForwarding){
                isForwarding = true
                val currentTime = System.currentTimeMillis()
                val timeSpent = currentTime - enterTime

                if(timeSpent < MIN_WAIT_TIME){
                    delay(MIN_WAIT_TIME - timeSpent)
                }
                // 通知跳转，如果是已经申明停止跳转，则不进行通知
                if(!stopForwardToNextActivity){
                    _shouldForwardToNextActivity.value = true
                }
            }
        }
    }
}